package com.gm.wj.service;

import com.gm.wj.config.RedisConfig;
import com.gm.wj.dao.CourseCategoryDAO;
import com.gm.wj.dao.SysCourseDAO;
import com.gm.wj.dto.MyCourseDTO;
import com.gm.wj.dto.StuByCourseDTO;
import com.gm.wj.dto.UserDTO;
import com.gm.wj.entity.*;
import com.gm.wj.redis.RedisService;
import com.gm.wj.util.CastUtils;
import com.gm.wj.util.MyPage;
import com.gm.wj.util.MyTime;
import com.gm.wj.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @program: wj
 * @description:
 * @author: Huang_shengjun
 * @create: 2020-08-31 15:28
 **/
@Slf4j
@Service
public class SysCourseService {

    @Autowired
    SysCourseDAO sysCourseDAO;
    @Autowired
    RedisService redisService;
    @Autowired
    CourseCategoryService courseCategoryService;
    @Autowired
    SysOrderFlowService sysOrderFlowService;
    @Autowired
    SysCourseService sysCourseService;
    @Autowired
    SysStudentService sysStudentService;
    @Autowired
    CourseCategoryDAO courseCategoryDAO;
    @Autowired
    PermissionURL permissionURL;

//    public MyPage list(int page, int size) {
//        MyPage<SysCourse> courses;
//        // list缓存
//        String key = "coursepage:" + page;
//        Object pageCache = redisService.get(key);
//
//        // 如果为空，就再查询一次，写入redis缓存
//        if (pageCache == null) {
//            Sort sort = Sort.by(Sort.Direction.DESC, "id");
//            Page<SysCourse> courseInDb = sysCourseDAO.findAll(PageRequest.of(page, size, sort));
//            courses = new MyPage<>(courseInDb);
//            // 设置redis过期时间  5s
//            redisService.set(key, courses, RedisConfig.DATA_REDIS_KEY_TIME);
//        } else {
//            courses = (MyPage<SysCourse>) pageCache;
//        }
//        return courses;
//    }


    public MyPage list(int page, int size, String queryKey1, String queryKey2, String queryKey3) {
        // 获取操作用户名
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        MyPage<SysCourse> courses;
        // list缓存
        String key =  username + "coursepage:" + page;
        Object pageCache = redisService.get(key);

        // 如果为空，就再查询一次，写入redis缓存
        if (pageCache == null) {
            Sort sort = Sort.by(Sort.Direction.DESC, "id");

            // 重写 findAll方法  多条件查询
            Pageable pageable = new PageRequest(page, size,sort);
            Page<SysCourse> courseInDb = sysCourseDAO.findAll((Specification<SysCourse>) (root, criteriaQuery, criteriaBuilder) -> {
                List<javax.persistence.criteria.Predicate> list = new ArrayList<Predicate>();
                // 实体类字段，不是数据库字段  只能获取已启用的数据
                list.add(criteriaBuilder.equal(root.get("display").as(Integer.class), 1));
                // 如果拥有权限  清除只能查询已启用的数据的条件查询
                if(permissionURL.isPermissionURL(SysCourse.class.getSimpleName(),username)){
                    list.removeAll(list);
                }
                if(!"".equals(queryKey3)&&null!=queryKey3){
                    list.add(criteriaBuilder.equal(root.get("display").as(Integer.class), queryKey3));
                }
                if(!"".equals(queryKey1)&&null!=queryKey1){
                    list.add(criteriaBuilder.like(root.get("courseName").as(String.class), "%" + queryKey1 + "%"));
                }
                if(!"".equals(queryKey2)&&null!=queryKey2){
                    list.add(criteriaBuilder.like(root.get("teacher").as(String.class), "%" + queryKey2 + "%"));
                }
                javax.persistence.criteria.Predicate[] p = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(p));
            },pageable);
            // findAll方法 重写结束

            courses = new MyPage<>(courseInDb);
            // 设置redis过期时间  5s
            redisService.set(key, courses, RedisConfig.DATA_REDIS_KEY_TIME);
        } else {
            courses = (MyPage<SysCourse>) pageCache;
        }
        return courses;
    }

    public SysCourse findById(int id) {
        SysCourse sysCourse;
        String key = "course:" + id;
        Object cache = redisService.get(key);

        if (cache == null) {
            sysCourse = sysCourseDAO.findById(id);
            redisService.set(key, sysCourse,RedisConfig.DATA_REDIS_KEY_TIME);
        } else {
            sysCourse = (SysCourse) cache;
        }
        return sysCourse;
    }

    public void addOrUpdate(SysCourse sysCourse) {
        // 如果为空，就是新的数据，如果不为空，就是以及存在的数据
        SysCourse sysCourse1 = findById(sysCourse.getId());

        if (sysCourse1 == null){
            sysCourse.setCourseId(StringUtils.getRandomString(8));
            sysCourse.setCreateTime( MyTime.getStringDate());
        } else {
            sysCourse.setCreateTime( sysCourse1.getCreateTime());
        }
        sysCourseDAO.save(sysCourse);
        redisService.delete("course" + sysCourse.getId());
        Set<String> keys = redisService.getKeysByPattern("coursepage*");
        redisService.delete(keys);
    }

    public void delete(int id) {
        sysCourseDAO.deleteById(id);
        redisService.delete("course:" + id);
        Set<String> keys = redisService.getKeysByPattern("coursepage*");
        redisService.delete(keys);
    }

    public void updateDisplay(SysCourse sysCourse) {
        SysCourse sysCourse1 = sysCourseDAO.findById(sysCourse.getId());
        sysCourse1.setDisplay(sysCourse.isDisplay());
        log.info(sysCourse1.toString());
        sysCourseDAO.save(sysCourse1);
    }


    /**
     *
     * @param queryKey1  course_name
     * @param queryKey2  teacher
     * @param queryKey3  type
     * @return
     */
    public List<SysCourse> listByQueryKey(String queryKey1, String queryKey2, String queryKey3) {

        // 多条件模糊查询
        queryKey1 = (queryKey1 == null) ? null : "%" + queryKey1 + "%";
        queryKey2 = (queryKey2 == null) ? null : "%" + queryKey2 + "%";
        queryKey3 = (queryKey3 == null && queryKey3 == "" ) ? null : "" + queryKey3 + ""; // booble值  直接用等于  不用like了
        log.info(queryKey1, queryKey2, queryKey3);
        List<SysCourse> sysCourses = sysCourseDAO.find(queryKey1, queryKey2, queryKey3);

        return sysCourses;
    }

    /**
     * 查询启动3个的数量
     * @return
     */
    public boolean findByDisplay(){
        List a = sysCourseDAO.findByDisplay(1);
        if (a.size() == 3 || a.size() <3){
            return false;
        }else {
            return true;
        }
    }

    /**
     * 已经启用的课程
     * @return
     */
    public List<SysCourse> findCourseByDisplay() {
        try {
            List<SysCourse> sysCourses = sysCourseDAO.findByDisplay();
            return sysCourses;
        } catch (Exception e){
            e.printStackTrace();
            List<SysCourse> sysCourses = null;
            return sysCourses;
        }

    }

    /**
     * 根据课程id查询拼团价格
     * @param courseId
     * @return
     */
    public SysCourse findByCourseId(String courseId) {
        return sysCourseDAO.findByCourseId(courseId);
    }

    /**
     *  开团，扣减库存
     */
    public void deductionStock(String courseId,int i) {
        sysCourseDAO.deductionStock(courseId,i);
    }

    /**
     *  拼团失败，归还库存
     */
    public void releaseStock(String courseId,int i) {
        sysCourseDAO.releaseStock(courseId,i);
    }

    /**
     * 首页-根据类型查询分类
     * @param cid
     * @return
     */
    public List<SysCourse> listByCategory(int cid) {
        return sysCourseDAO.findAllByCourseType(cid);
    }

    /**
     * 首页-根据关键字查询
     * @param keywords
     * @return
     */
    public List<SysCourse> Search(String keywords) {
        return sysCourseDAO.findAllByCourseNameOrTeacher('%' + keywords + '%', '%' + keywords + '%');
    }

    /**
     * 首页-全部
     * @return
     */
    public List<SysCourse> list() {
        try {
            List<SysCourse> sysCourses;
            String key = "SysCourselist";
            Object sysCoursesCache = redisService.get(key);

            if (sysCoursesCache == null) {
                sysCourses = findCourseByDisplay();
                redisService.set(key, sysCourses, RedisConfig.DATA_REDIS_KEY_TIME);
            } else {
                sysCourses = CastUtils.objectConvertToList(sysCoursesCache, SysCourse.class);
            }
            return sysCourses;
        } catch ( Exception e){
            e.printStackTrace();
            List<SysCourse> sysCourses = null;
            return sysCourses;
        }
    }

    /**
     * 我的课程信息获取
     * @return
     */
    public List<MyCourseDTO> listByMy() {
        String username = SecurityUtils.getSubject().getPrincipal().toString();
        List<SysOrder> sysOrderList = sysOrderFlowService.findOrderByUsername(username);
        // 订单状态；0-待支付，1-已支付，2-已过期，3-已退款，4-退款失败
        sysOrderList.removeIf(m -> m.getOrderStatus() != 1);
        List<MyCourseDTO> myCourseDTOList = new ArrayList<>();
        if (sysOrderList.size() > 0) {
//            myCourseDTOList = sysOrderList
//                    .stream().map(myCourse -> (MyCourseDTO) new MyCourseDTO().convertFrom(myCourse)).collect(Collectors.toList());
            sysOrderList.forEach(u ->{
                MyCourseDTO myCourseDTO = new MyCourseDTO();
                myCourseDTO.setProductId(u.getProductId());
                myCourseDTO.setPayAmount(u.getPayAmount());
                myCourseDTO.setPayTime(u.getPayTime());
                myCourseDTO.setProductName(u.getProductName());
                myCourseDTOList.add(myCourseDTO);
            });
        }
        return myCourseDTOList;
    }

    /**
     * 根据课程id查询该课程下的报名用户
     * @param courseId
     * @return
     */
    public List<StuByCourseDTO> getStuListByCourseId(String courseId) {
        List<SysOrder> sysOrderList = sysOrderFlowService.findOrderByCourseId(courseId);
        // 订单状态；0-待支付，1-已支付，2-已过期，3-已退款，4-退款失败
        sysOrderList.removeIf(m -> m.getOrderStatus() != 1);
        List<StuByCourseDTO> stuByCourseDTOArrayList = new ArrayList<>();
        if (sysOrderList.size() > 0) {
            sysOrderList.forEach(u -> {
                StuByCourseDTO stuByCourseDTO = new StuByCourseDTO();
                SysStudent sysStudent = sysStudentService.findByUsername(u.getUsername());
                if (sysStudent != null) {
                    stuByCourseDTO.setStuNo(sysStudent.getStuNo());
                    stuByCourseDTO.setPhone(sysStudent.getPhone());
                    stuByCourseDTO.setStuName(sysStudent.getStuName());
                    stuByCourseDTO.setUsername(sysStudent.getUsername());
                    stuByCourseDTO.setCreateTime(u.getCreateTime());
                    stuByCourseDTO.setPayAmount(u.getPayAmount());
                    stuByCourseDTOArrayList.add(stuByCourseDTO);
                }
            });
        }
        return stuByCourseDTOArrayList;
    }

    /**
     * 查找全部的课程类型  用于选择课程类型以及侧边栏菜单
     * @return
     */
    public List<CourseCategory> courseTypeList() {
        return courseCategoryDAO.findAll();
    }
}
